package com.heima.wemedia.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.constants.message.WmNewsUpDownConstants;
import com.heima.common.dtos.PageResult;
import com.heima.common.dtos.ResponseResult;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.enums.WmNewsStatusEnum;
import com.heima.common.exception.LeadException;
import com.heima.common.threadlocal.UserThreadLocalUtils;
import com.heima.common.util.BeanHelper;
import com.heima.common.util.JsonUtils;
import com.heima.feign.ApArticleFeignClient;
import com.heima.dto.ApAuthor;
import com.heima.feign.ApArticleFeignClient;
import com.heima.model.admin.dtos.NewsAuthDto;
import com.heima.model.media.dtos.WmNewsResultDTO;
import com.heima.model.wemedia.dto.WmNewsPageDTO;
import com.heima.model.media.dtos.WmNewsDownOrUpDTO;
import com.heima.model.media.dtos.WmNewsDto;
import com.heima.model.media.dtos.WmNewsPageReqDto;
import com.heima.wemedia.entity.WmNews;
import com.heima.wemedia.entity.WmUser;
import com.heima.wemedia.entity.WmNewsPageVO;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.service.WmAuditService;
import com.heima.wemedia.service.WmNewsMaterialService;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.service.WmUserService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 自媒体图文内容信息表 服务实现类
 * </p>
 *
 * @author HM
 * @since 2023-03-22
 */
@Slf4j
@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Autowired
    private WmNewsMaterialService materialService;
    @Autowired
    @Lazy
    private WmAuditService wmAuditService2;
    @Autowired
    private ApArticleFeignClient articleFeignClient;

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;
    @Autowired
    private WmNewsMaterialService newsMaterialService;
    @Autowired
    private ApArticleFeignClient client;

    @Override
    public void downOrUp(WmNewsDownOrUpDTO dto) {
        // 查询是否存在
        WmNews newsDB = this.getById(dto.getId());
        if (newsDB == null) {
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        // 校验状态
        if (newsDB.getStatus() != 9) {//TODO
            throw new LeadException(AppHttpCodeEnum.NO_OPERATOR_AUTH);
        }
        // 校验用户
        if (!Objects.equals(newsDB.getWmUserId(), UserThreadLocalUtils.getUserId())) {
            throw new LeadException(AppHttpCodeEnum.NO_OPERATOR_AUTH);
        }
        if (Objects.equals(newsDB.getEnable(), dto.getEnable())) {
            return;
        }
        // 更新上下架的状态
        WmNews updateNews = new WmNews();
        updateNews.setId(dto.getId());
        updateNews.setEnable(dto.getEnable());
        this.updateById(updateNews);
        // 发送消息
        dto.setArticleId(newsDB.getArticleId());
        String message = JsonUtils.toString(dto);

        kafkaTemplate.send(WmNewsUpDownConstants.WM_NEWS_UP_OR_DOWN_TOPIC, message);
    }

    /**
     * 自媒体用户登录后，删除自媒体文章，如果已经通过审核发布的文章不能删除
     *
     * @param id 自媒体文章id
     */
    @Override
    @GlobalTransactional
    public void deleteById(Integer id) {
        WmNews wmNewsDB = this.getById(id);
        // 数据库数据查询数据判空
        if (wmNewsDB == null) {
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        // 当文章处于上架发布状态，不能删除
        if (wmNewsDB.getEnable()) {
            throw new LeadException(AppHttpCodeEnum.WM_NEWS_STATUS_ERROR);
        }
        // 判断用户ID是否一致
        if (!wmNewsDB.getWmUserId().equals(UserThreadLocalUtils.getUserId())) {
            throw new LeadException(AppHttpCodeEnum.UAER_NO_OPERATOR_AUTH);
        }
        // 已发布文章删除
        if (wmNewsDB.getStatus() == WmNewsStatusEnum.HAVE_PUBLISHED.getStatus()) {
            // 删除已发布的文章
            articleFeignClient.delArticleByNewsId(wmNewsDB.getWmUserId(), id);
        }
        // 删除关联关系
        newsMaterialService.deleteByWmNewsId(id);
        // 删除自媒体文章
        this.removeById(id);
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void submit(WmNewsDto dto) {
        Integer wmNewsId = dto.getId();
        // 是否是草稿
        Boolean draft = dto.getDraft();
        // 保存wm_news
        if (dto.getId() != null && dto.getId() > 0) {
            //  修改
            WmNews wmNewsDB = this.getById(dto.getId());
            if (wmNewsDB == null) {
                throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
            }
            WmNews updateWmNews = BeanHelper.copyProperties(dto, WmNews.class);
            List<String> images = dto.getImages();
            if (!CollectionUtils.isEmpty(images)) {
                updateWmNews.setImages(images.stream().collect(Collectors.joining(",")));
            }
            if (dto.getPublishTime() == null) {
                updateWmNews.setPublishTime(new Date());
            }
            if (!draft) {
                updateWmNews.setSubmitedTime(new Date());
            }
            updateWmNews.setEnable(false);
            this.updateById(updateWmNews);
        } else {
            // insert
            WmNews insertWmNews = BeanHelper.copyProperties(dto, WmNews.class);
            List<String> images = dto.getImages();
            if (!CollectionUtils.isEmpty(images)) {
                insertWmNews.setImages(images.stream().collect(Collectors.joining(",")));
            }
            if (dto.getPublishTime() == null) {
                insertWmNews.setPublishTime(new Date());
            }
            insertWmNews.setWmUserId(UserThreadLocalUtils.getUserId());
            insertWmNews.setCreatedTime(new Date());
            if (!draft) {
                insertWmNews.setSubmitedTime(new Date());
            }
            insertWmNews.setEnable(false);
            this.save(insertWmNews);
            wmNewsId = insertWmNews.getId();
            dto.setId(wmNewsId);
        }
        // 保存news_material关联关系
        materialService.deleteByWmNewsId(wmNewsId);
        materialService.insertByWmNews(dto);
        if (draft) {
            // 说明时草稿的处理，结束
            return;
        }
        // 异步审核
        log.info("准备开始异步审核");
        wmAuditService2.asyncAudit(UserThreadLocalUtils.getUserId(), dto);
    }

    @Override
    public PageResult<WmNews> findByPage(WmNewsPageReqDto dto) {
        LambdaQueryWrapper<WmNews> queryWrapper = new LambdaQueryWrapper<>();
        // 设置查询的 状态 条件
        setQueryStatus(dto, queryWrapper);
        queryWrapper.eq(dto.getChannelId() != null, WmNews::getChannelId, dto.getChannelId());
        queryWrapper.like(StringUtils.isNotEmpty(dto.getKeyword()), WmNews::getTitle, dto.getKeyword());
        queryWrapper.ge(dto.getBeginPubDate() != null, WmNews::getPublishTime, dto.getBeginPubDate());
        queryWrapper.le(dto.getEndPubDate() != null, WmNews::getPublishTime, dto.getEndPubDate());
        queryWrapper.eq(WmNews::getWmUserId, UserThreadLocalUtils.getUserId());
        // 分页查询数据
        Page<WmNews> wmNewsPage = new Page<>(dto.getPage(), dto.getSize());
        Page<WmNews> page = this.page(wmNewsPage, queryWrapper);
        return new PageResult<>(dto.getPage(), dto.getSize(), page.getTotal(), page.getRecords());
    }

    private void setQueryStatus(WmNewsPageReqDto dto, LambdaQueryWrapper<WmNews> queryWrapper) {
        if (dto.getStatus() != null) {
            ArrayList<Integer> statusList = new ArrayList<>();
            if (dto.getStatus() == 0) {
                statusList.add(0);
            } else if (dto.getStatus() == 1) {
                statusList.add(1);
                statusList.add(3);
            } else if (dto.getStatus() == 2) {
                statusList.add(2);
            } else if (dto.getStatus() == 4) {
                statusList.add(4);
                statusList.add(8);
                statusList.add(9);
            }
            if (!CollectionUtils.isEmpty(statusList)) {
                queryWrapper.in(dto.getStatus() != null, WmNews::getStatus, statusList);
            }
        }
    }

    /**
     * 根据id查询文章详情
     *
     * @param id
     * @return
     */
    @Autowired
    private WmUserService wmUserService;

    @Override
    public ResponseResult findById(Integer id) {
        //根据id查询news
        WmNews wmNews = this.getById(id);
        if (wmNews == null) {
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        WmNewsDto wmNewsDto = BeanHelper.copyProperties(wmNews, WmNewsDto.class);
        //封装数据
        WmUser wmUser = wmUserService.getById(wmNews.getWmUserId());
        wmNewsDto.setAuthorName(wmUser.getName());
        return ResponseResult.ok(wmNewsDto);
    }

    @Override
    public List<WmNewsPageVO> listByTitle(WmNewsPageDTO dto) {
        LambdaQueryWrapper<WmNews> queryWrapper = new LambdaQueryWrapper<>();
        if (dto.getStatus() != null && dto.getStatus() != 0) {
            queryWrapper.eq(WmNews::getStatus, dto.getStatus());
        }
        queryWrapper.like(!StringUtils.isEmpty(dto.getTitle()), WmNews::getTitle, dto.getTitle());
        queryWrapper.orderByDesc(WmNews::getCreatedTime);
        Page<WmNews> page = new Page<>(dto.getPage(), dto.getSize());
        page(page, queryWrapper);
        List<WmNews> records = page.getRecords();
        List<WmNewsPageVO> list = records.stream().map(wmNews -> {
            WmNewsPageVO vo = BeanHelper.copyProperties(wmNews, WmNewsPageVO.class);
            vo.setUserId(wmNews.getWmUserId());
            vo.setAuthorName(client.getAuthorByUserId(wmNews.getWmUserId()).getName());
            return vo;
        }).collect(Collectors.toList());
        return list;
    }

    /**
     * 文章人工审核通过
     *
     * @param newsId
     */
    @Override
    public WmNews authPass(Integer newsId) {
        WmNews wmNews = getById(newsId);
        if (wmNews == null) {
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        // 把wmNews发布成article,feign
        Long articleId = articleFeignClient.createArticle(buildWmNewsResultDTO(wmNews));

        //回填article_id， 修改审核状态
        updateWmNewsInfo(newsId, WmNewsStatusEnum.HAVE_PUBLISHED.getStatus(), articleId, "", true);
        return wmNews;
    }

    @Override
    public void authFail(NewsAuthDto dto) {
        WmNews wmNewsDB = this.getById(dto.getId());
        if (wmNewsDB == null) {
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        wmNewsDB.setStatus(WmNewsStatusEnum.AUDIT_FAILURE.getStatus());
        this.updateById(wmNewsDB);
    }

    private void updateWmNewsInfo(Integer wmNewsId, Integer status, Long articleId, String reason, Boolean enable) {
        WmNews updateWmNews = new WmNews();
        updateWmNews.setId(wmNewsId);
        updateWmNews.setStatus(status);
        if (articleId != null) {
            updateWmNews.setArticleId(articleId);
        }
        if (enable != null) {
            updateWmNews.setEnable(enable);
        }
        updateWmNews.setReason(reason);
        updateById(updateWmNews);
    }

    private WmNewsResultDTO buildWmNewsResultDTO(WmNews wmNews) {
        WmNewsResultDTO wmNewsResultDTO = new WmNewsResultDTO();
        wmNewsResultDTO.setId(wmNews.getId());
        wmNewsResultDTO.setWmUserId(wmNewsResultDTO.getWmUserId());
        wmNewsResultDTO.setTitle(wmNewsResultDTO.getTitle());
        wmNewsResultDTO.setContent(wmNewsResultDTO.getContent());
        wmNewsResultDTO.setType(wmNewsResultDTO.getType());
        wmNewsResultDTO.setChannelId(wmNewsResultDTO.getChannelId());
        wmNewsResultDTO.setChannelName("ch_name");// TODO
        wmNewsResultDTO.setLabels(wmNewsResultDTO.getLabels());
        //如果没有发布时间，默认是当前时间
        wmNewsResultDTO.setPublishTime(wmNews.getPublishTime() == null ? new Date() : wmNews.getPublishTime());
        wmNewsResultDTO.setImages(StringUtils.isEmpty(wmNews.getImages()) ? null : wmNews.getImages());
        return wmNewsResultDTO;
    }

}
